#!usr/bin/python
# -*- coding: utf8 -*-
encoding='utf8'
'''утф'''

import os, sys

## Start concatenation ##

class Unnamed_singleton(object):
    count = 0

    def __init__(self):
        self.prefix = u'__unnamed__'

    def create(self):
        name = u'%s%d' % (self.prefix, self.count)
        self.count+= 1
        return name

class Namespace(object):
    unnamed = Unnamed_singleton()
    def __init__(self, name = None, parent_ns = None):
        self.parent_ns = parent_ns
        self.name = name
        self.variables = []
        self.constants = []
        self.functions = []
        self.types = []
        self.children = []
        #if not parent_ns:
        self.initAs_global()

    def getDefault_name(self):
        return self.unnamed.create()

    def setParent_namespace(self, parent_ns):
        self.parent_ns = parent_ns

    def createChild(self, name):
        child = Namespace(name, self)
        self.addChild(child)
        return child

    def addChild(self, child):
        self.children.append(child)

    def removeChild(self, name):
        for c in range(len(self.children)):
            if self.children[c].name == name:
                del self.children[c]
                return

    def addVariable(self, token):
        vname = token.name
        for id, var in enumerate(self.variables):
            if vname == var.name:
                print token.origin.debug()
                err_msg = u'Error in Namespace.addVariable: Variable "%s" allready defined.' % (vname)
                raise(ValueError(err_msg))
                del self.variables[id]
        self.variables.append(token)

    def addConstant(self, token):
        self.constants.append(token)

    def addFunction(self, token):
        self.functions.append(token)

    def addType(self, token):
        self.types.append(token)

    def isVariable(self, token):
        for var in self.variables:
            if token.text() == var.name:
                return True
        if self.parent_ns:
            if self.parent_ns.isVariable(token):
                return True
        return False

    def isConstant(self, token):
        for var in self.constants:
            if token.text() == var.name:
                return True
        return False

    def isFunction(self, token):
        for func in self.functions:
            if token.text() == func.name:
                return True
        if self.parent_ns:
            if self.parent_ns.isFunction(token):
                return True
        return False

    def isType(self, token):
        for t in self.types:
            if token.text() == t.name:
                return True
        if self.parent_ns:
            if self.parent_ns.isType(token):
                return True
        elif token.text() in self.builtin_types:
            return True
        return False

    def getVariable(self, token):
        for var in self.variables:
            if token.text() == var.name:
                return var
        for var in self.constants:
            if token.text() == var.name:
                return var
        return None

    def getType(self, token):
        for t in self.types:
            if token.text() == t.name:
                return t
        if self.parent_ns:
            return self.parent_ns.getType(token)
        elif token.text() in self.builtin_types:
            return None
        return None

    def getFunction(self, token):
        for t in self.functions:
            if token.text() == t.name:
                return t
        if self.parent_ns:
            return self.parent_ns.getFunction(token)
        return None

    def isNamespace(self, token):
        for c in self.children:
            if c.name == token.text():
                return True
        return False

    def isNamespace_keyword(self, token):
        for c in self.namespace_kw:
            if c == token.text():
                return True
        return False

    def isKeyword(self, token):
        if self.isIdent(token):  
            if token.text() in self.keywords + self.type_kw + self.storage_kw:
                return True
        else:
            return False

    def isIdent(self, token):
        if token.type == 'ident':
            return True
        else:
            return False

    def getSize(self, token):
        if self.type_sizes.has_key(token.text()):
            return self.type_sizes[token.text()]
        t = self.getType(token)
        if t:
            return t.size()

    def initAs_global(self):
        self.builtin_types = [
            ## Built-in types:
            u'char', u'bool', u'double', u'float', u'int', u'long',
            u'short', u'signed', u'unsigned', u'void',
            #u'shortad',
            u'non_banked', u'banked', 
                     ]
        self.type_sizes = {
            u'bool'         : 1,
            u'char'         : 1,
            u'short'        : 2,
            u'int'          : 2,
            u'float'        : 4,
            u'long'         : 4,
            u'double'       : 8,
            u'signed'       : 0,
            u'unsigned'     : 0,
            u'void'         : 0,
            u'shortad'      : 0,
            u'non_banked'   : 0,
            u'banked'       : 0, 
        }
        self.storage_kw = (
            ## Storage modifier
            u'auto', u'register', u'static', u'volatile', u'extern',
                          )
        self.namespace_kw = (
            u'typedef', u'struct', u'enum', u'union'
                            )
        self.keywords = (
            ## Branching:
            u'while', u'if', u'else', u'for', u'do', u'goto', u'return',
            u'switch', u'case', u'break', u'continue', u'default',
            ## Other:
            u'true', u'false', u'sizeof', u'const',
            ## Windows-specific:
            u'__asm', u'__based1', u'__cdecl', u'__declspec', u'__except',
            u'__fastcall', u'__finally', u'__inline', u'__int16', u'__int32',
            u'__int64', u'__int8', u'__leave', u'__stdcall', u'__try',
            u'dllexport2', u'dllimport2', u'naked2', u'thread2'
                        )

    def text(self, indent = 0):
        output = u''
        if self.name:
            output+= u' '*indent + u'Namespace %s:\n' % (self.name)
            indent+= 4
        sindent = u' '*indent
        if len(self.children):
            output+= sindent + u'// Namespaces (%d):\n' % (len(self.children))
            for t in self.children:
                output+= sindent*2 + t.text(indent) + u'\n'
        if len(self.types):
            output+= sindent + u'// Types (%d):\n' % (len(self.types))
            for t in self.types:
                output+= sindent*2 + t.text() + u';\n'
        if len(self.variables):
            output+= sindent + u'// Variables (%d):\n' % (len(self.variables))
            for v in sorted( self.variables, lambda a,b: cmp(a.name, b.name) ):
                output+= sindent*2 + v.text() + u';\n'
        if len(self.functions):
            output+= sindent + u'// Functions (%d):\n' % (len(self.functions))
            for f in self.functions:
                output+= sindent*2 + f.text() + u'\n'
        return output

## Stop concatenation ##

def main():
    pass

if __name__ == '__main__':
    main()
